package dev.meow.core;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.Security;
import java.util.List;

import javax.smartcardio.Card;
import javax.smartcardio.CardChannel;
import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.CardTerminals;
import javax.smartcardio.CardTerminals.State;
import javax.smartcardio.CommandAPDU;
import javax.smartcardio.ResponseAPDU;
import javax.smartcardio.TerminalFactory;

import com.sun.corba.se.impl.ior.ByteBuffer;

import de.intarsys.security.smartcard.smartcardio.SmartcardioProvider;

public class SMCCore {

	private byte[] header1;
	private byte[] header2;
	private byte[] responeData;
	private byte[] imageData;

	protected void connect(CardTerminal cardTerminal) throws Exception {
		System.out.println("" + cardTerminal + " connect "
				+ cardTerminal.getName());
		Card card = cardTerminal.connect("*");
		try {
			CardChannel channel = card.getBasicChannel();
			System.out.println("ATR : " + card.getATR().toString());
			System.out.println("FB : " + card.getATR().getBytes()[0] + " > "	+ Integer.toHexString(card.getATR().getBytes()[0]));
			System.out.println("SB : " + card.getATR().getBytes()[1] + " > "	+ Integer.toHexString(card.getATR().getBytes()[1]));

			// read cmd // Send SELECT/RESET command
			CommandAPDU commandAPDU = new CommandAPDU(SMC_TH.CMD_SELECT);
			ResponseAPDU responseAPDU = channel.transmit(commandAPDU);
			System.out.println("DATA rHeader : "
					+ responseAPDU.getData().length);

			// byte[] header = new byte[] { (byte) 0x80, (byte) 0xb0, 0x00,
			// 0x04,
			// 0x02, 0x00, 0x0d };
			commandAPDU = new CommandAPDU(header1);
			responseAPDU = channel.transmit(commandAPDU);
			System.out
					.println("DATA header : " + responseAPDU.getData().length);

			// byte[] header2 = new byte[] { 0x00, (byte) 0xc0, 0x00, 0x00, 0x0d
			// };
			commandAPDU = new CommandAPDU(header2);
			responseAPDU = channel.transmit(commandAPDU);
			System.out.println("DATA header2 : "
					+ responseAPDU.getData().length);

			System.out.println();
			System.out.println(new String(responseAPDU.getData(), "TIS-620"));
			System.out.println("L : " + responseAPDU.getBytes().length);
			responeData = responseAPDU.getData();

		} finally {
			System.out.println("" + card + " disconnect");
			card.disconnect(false);
		}
	}
	protected void photoCmd(CardTerminal cardTerminal) throws Exception {
		System.out.println("" + cardTerminal + " connect "
				+ cardTerminal.getName());
		Card card = cardTerminal.connect("*");
		try {
			CardChannel channel = card.getBasicChannel();
			System.out.println("ATR : " + card.getATR().toString());
			System.out.println("FB : " + card.getATR().getBytes()[0] + " > "+ Integer.toHexString(card.getATR().getBytes()[0]));
			System.out.println("SB : " + card.getATR().getBytes()[1] + " > "+ Integer.toHexString(card.getATR().getBytes()[1]));
			
			// read cmd // Send SELECT/RESET command
			CommandAPDU commandAPDU = new CommandAPDU(SMC_TH.CMD_SELECT);
			ResponseAPDU responseAPDU = channel.transmit(commandAPDU);
			System.out.println("DATA rHeader : "+ responseAPDU.getData().length);
			
			//photo cmd
			  ByteBuffer s = new ByteBuffer();
			  	//all cmd
	            CMDP[] cmds_photo = SMC_TH.GET_CMD_CARD_PHOTO();

	            for (int i = 0; i < cmds_photo.length; i++)
	            {
	                byte[] recv1 = null ;
	                
	    			commandAPDU = new CommandAPDU(cmds_photo[i].CMD1);
	    			recv1 = channel.transmit(commandAPDU).getData();
	    			System.out.println("recv1 : " + recv1.length);
	                if (recv1.length >= 0)
	                {
	                    byte[] recv2 = null;
//	                    _err = _reader.Transmit(_pioSendPci, cmds_photo[i].CMD2, ref recv2);
//	                    CheckErr(_err);
		    			commandAPDU = new CommandAPDU(cmds_photo[i].CMD2);
		    			recv2 = channel.transmit(commandAPDU).getData();
	                    System.out.println("P recv2 size : " + recv2.length);
	                    for(byte b : recv2){
	                    	s.append(b);
	                    }
	                }
	            }

			System.out.println("DATA image : " + s.size());
			imageData = s.toArray();
//			this.writeFile(s.toArray());
			
			
		} finally {
			System.out.println("" + card + " disconnect");
			card.disconnect(false);
		}
	}

	public byte[] runcmd(byte[][] cmd) {
		this.header1 = cmd[0];
		this.header2 = cmd[1];
		try {
			run();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return this.responeData;
	}

	public void run() throws Exception {
		Security.insertProviderAt(new SmartcardioProvider(), 1);
		//
		TerminalFactory factory = TerminalFactory.getDefault();
		CardTerminals terminals = factory.terminals();
		// while (System.in.available() == 0) {
		List<CardTerminal> list = terminals.list(State.CARD_INSERTION);
		if (list.isEmpty()) {
			System.out.println("no terminals");
		}
		for (CardTerminal cardTerminal : list) {
			try {
				connect(cardTerminal);
				break;
			} catch (Exception e) {
				System.out.println("error connecting " + e);
			}
		}
	}
	
	public byte[] getPhoto() {
		try {
			Security.insertProviderAt(new SmartcardioProvider(), 1);
			TerminalFactory factory = TerminalFactory.getDefault();
			CardTerminals terminals = factory.terminals();
			List<CardTerminal> list;
			list = terminals.list(State.CARD_INSERTION);
			if (list.isEmpty()) {
				System.out.println("no terminals");
			}
			for (CardTerminal cardTerminal : list) {
				try {
					this.photoCmd(cardTerminal);
					break;
				} catch (Exception e) {
					e.printStackTrace();
					System.out.println("error connecting " + e);
				}
			}
		} catch (CardException e1) {
			e1.printStackTrace();
		}

		return imageData;
	}

	public static void writeFile(String path ,String fileName , byte[] data){
		FileOutputStream fileOutputStream = null ;
		path = (path == null)? "" : path;
		try {
			fileOutputStream = new FileOutputStream( path + fileName +  ".jpg");
			fileOutputStream.write(data);
			System.out.println("Fin : " + data.length);
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
				fileOutputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	public PersonData getTH_IC_DATA(){
		PersonData personData = new PersonData();
		try {
		byte[] res;
		//IC
		res= new SMCCore().runcmd(SMC_TH.CMD_CID);
		personData.setpId(new String(res,"TIS-620"));
		//PERSON 
		res = new SMCCore().runcmd(SMC_TH.CMD_PERSON_INFO);
		personData.setPersonInfo(new String(res,"TIS-620"));
		//ADDR
		res = new SMCCore().runcmd(SMC_TH.CMD_ADDRESS);
		personData.setAddr(new String(res,"TIS-620"));
		//EXPIRE
		res = new SMCCore().runcmd(SMC_TH.CMD_CARD_ISSUE_EXPIRE);
		personData.setExpire(new String(res,"TIS-620"));
		//Img
		res = new SMCCore().getPhoto();
		personData.setImage(res);
		
		
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		
		return personData;
	}
	
	public static void main(String[] args) {
//		byte[] res = new SMCCore().runcmd(SMC_TH.CMD_CID);
//		res = new SMCCore().runcmd(SMC_TH.CMD_PERSON_INFO);
//		res = new SMCCore().runcmd(SMC_TH.CMD_ADDRESS);
//		res = new SMCCore().runcmd(SMC_TH.CMD_CARD_ISSUE_EXPIRE);
//		System.out.println(res);
//		 new SMCCore().getPhoto();
		PersonData p = new SMCCore().getTH_IC_DATA();
		p.writeFile("", "pimage");
		System.out.println(p);
		
	}

}
